﻿Imports System.ComponentModel
Imports System.Linq.Expressions

Public Class VM_PublisherCard
	Inherits AutomaticNotfiyPropertyChanged
	Implements IDisposable

	Dim db As New CongregationDataContainerLocal

	Dim _PublisherID As Long

	Public ReadOnly Property PublisherName As String
		Get
			'Using db As New CongregationDataContainerLocal

			Return db.PublisherDatas.SingleOrDefault(Function(x) x.PublisherID = _PublisherID).FullName
			'End Using
		End Get
	End Property

	Public ReadOnly Property IsPioneer As Boolean
		Get
			'Using db As New CongregationDataContainerLocal

			Return db.PublisherDatas.SingleOrDefault(Function(x) x.PublisherID = _PublisherID).IsPioneer
			'End Using
		End Get
	End Property

	Private ReadOnly Property MonthsFromSeptember(Optional StartDate As DateTime? = Nothing) As Integer
		Get
			If StartDate Is Nothing Then
				StartDate = Now
			End If

			Dim monthCount As Integer

			For x = 0 To 11
				If StartDate.Value.AddMonths(-x).Month = 9 Then
					monthCount = x
					Exit For
				End If
			Next

			Return monthCount
		End Get
	End Property

	Private Function GetServiceYearStartDate(DateInServiceYear As DateTime) As DateTime
		Do While DateInServiceYear.Month <> 9
			DateInServiceYear = DateInServiceYear.AddMonths(-1)
		Loop

		Return DateInServiceYear.FirstOfTheMonth
	End Function

	Private Function GetServiceYearEndDate(DateInServiceYear As DateTime) As DateTime
		Do
			DateInServiceYear = DateInServiceYear.AddMonths(1)
		Loop While (DateInServiceYear.Month <> 9)

		'the day before the first day of the next service year is the last day of the previous service year
		Return DateInServiceYear.FirstOfTheMonth.AddDays(-1)
	End Function


	Public ReadOnly Property BooksForServiceYear(DateInServiceYear As DateTime) As Integer
		Get
			Return AllPublisherRecords.Where(Function(x) x.ReportMonth >= GetServiceYearStartDate(DateInServiceYear) AndAlso x.ReportMonth < GetServiceYearEndDate(DateInServiceYear)).Sum(Function(x) x.Books)
		End Get
	End Property

	Public ReadOnly Property BrochuresForServiceYear(DateInServiceYear As DateTime) As Integer
		Get
			Return AllPublisherRecords.Where(Function(x) x.ReportMonth >= GetServiceYearStartDate(DateInServiceYear) AndAlso x.ReportMonth < GetServiceYearEndDate(DateInServiceYear)).Sum(Function(x) x.Brochures)
		End Get
	End Property

	Public ReadOnly Property HoursForServiceYear(DateInServiceYear As DateTime) As Decimal
		Get
			Return AllPublisherRecords.Where(Function(x) x.ReportMonth >= GetServiceYearStartDate(DateInServiceYear) AndAlso x.ReportMonth < GetServiceYearEndDate(DateInServiceYear)).Sum(Function(x) x.Hours)
		End Get
	End Property

	Public ReadOnly Property PioneerHoursForServiceYear(DateInServiceYear As DateTime) As Integer
		Get
			Return AllPublisherRecords.Where(Function(x) x.ReportMonth >= GetServiceYearStartDate(DateInServiceYear) AndAlso x.ReportMonth < GetServiceYearEndDate(DateInServiceYear) AndAlso x.IsPioneer).Sum(Function(x) x.PioneerHours)
		End Get
	End Property

	Public ReadOnly Property PioneerHoursPaceForServiceYear(DateInServiceYear As DateTime) As Integer
		Get
			'number of months pioneering * 70 hours/month - how many credit hours they have - how many hours they got during the months they were pioneering
			Dim monthsPioneeringForServiceYear As Integer = AllPublisherRecords.Where(Function(x) x.ReportMonth >= GetServiceYearStartDate(DateInServiceYear) AndAlso x.ReportMonth < GetServiceYearEndDate(DateInServiceYear) AndAlso x.IsPioneer AndAlso x.Hours > 0).Count
			Dim pioneerHourRequirement As Integer = 70
			Return PioneerHoursForServiceYear(DateInServiceYear) - (monthsPioneeringForServiceYear * pioneerHourRequirement)
		End Get
	End Property

	Public ReadOnly Property MagazinesForServiceYear(DateInServiceYear As DateTime) As Integer
		Get
			Return AllPublisherRecords.Where(Function(x) x.ReportMonth >= GetServiceYearStartDate(DateInServiceYear) AndAlso x.ReportMonth < GetServiceYearEndDate(DateInServiceYear)).Sum(Function(x) x.Magazines)
		End Get
	End Property

	Public ReadOnly Property ReturnVisitsForServiceYear(DateInServiceYear As DateTime) As Integer
		Get
			Return AllPublisherRecords.Where(Function(x) x.ReportMonth >= GetServiceYearStartDate(DateInServiceYear) AndAlso x.ReportMonth < GetServiceYearEndDate(DateInServiceYear)).Sum(Function(x) x.ReturnVisits)
		End Get
	End Property

	Public ReadOnly Property BibleStudiesForServiceYear(DateInServiceYear As DateTime) As Integer
		Get
			Return AllPublisherRecords.Where(Function(x) x.ReportMonth >= GetServiceYearStartDate(DateInServiceYear) AndAlso x.ReportMonth < GetServiceYearEndDate(DateInServiceYear)).Sum(Function(x) x.BibleStudies)
		End Get
	End Property

	Public ReadOnly Property HoursThisServiceYear As Decimal
		Get
			Return AllPublisherRecords.Where(Function(x) x.ReportMonth >= Now.AddMonths(-MonthsFromSeptember).FirstOfTheMonth).Sum(Function(x) x.Hours)
		End Get
	End Property

	Public ReadOnly Property PioneerHoursThisServiceYear As Integer
		Get
			Return AllPublisherRecords.Where(Function(x) x.ReportMonth >= Now.AddMonths(-MonthsFromSeptember).FirstOfTheMonth AndAlso x.IsPioneer).Sum(Function(x) x.PioneerHours)
		End Get
	End Property

	Public ReadOnly Property PioneerHoursPaceThisServiceYear As Integer
		Get
			'number of months pioneering * 70 hours/month - how many credit hours they have - how many hours they got during the months they were pioneering
			Dim monthsPioneeringThisServiceYear As Integer = AllPublisherRecords.Where(Function(x) x.ReportMonth >= Now.AddMonths(-MonthsFromSeptember).FirstOfTheMonth AndAlso x.IsPioneer AndAlso x.Hours > 0).Count
			Dim pioneerHourRequirement As Integer = 70
			Return PioneerHoursThisServiceYear - (monthsPioneeringThisServiceYear * pioneerHourRequirement)
		End Get
	End Property

	Public ReadOnly Property HoursLastSixMonths As Decimal
		Get
			Return AllPublisherRecords.Where(Function(x) x.ReportMonth >= Now.AddMonths(-6).FirstOfTheMonth).Sum(Function(x) x.Hours)
		End Get
	End Property

	Dim _AllPublisherRecords As New BindingList(Of VM_PublisherCardRecord)
	Public ReadOnly Property AllPublisherRecords As BindingList(Of VM_PublisherCardRecord)
		Get
			Return _AllPublisherRecords
		End Get
	End Property

	Public Sub New(PublisherID As Long)
		_PublisherID = PublisherID
		'Using db As New CongregationDataContainerLocal
		Dim myPublisherRecords As New List(Of VM_PublisherCardRecord)

		Dim publisherRecords = db.PublisherCardDatas.Where(Function(x) x.PublisherID = PublisherID)

		myPublisherRecords.AddRange(publisherRecords.ToList.Select(Function(pubRecord) New VM_PublisherCardRecord(pubRecord.PublisherID, pubRecord.Month)).AsParallel.ToList)

		'we have to make sure there are mock records for every month since they began publishing here
		Dim publisherRecord = db.PublisherDatas.SingleOrDefault(Function(x) x.PublisherID = _PublisherID)
		If publisherRecord IsNot Nothing Then
			'we will also add older records for historical adding purposes
			'only if the existing records don't go back 13 months		
			Dim historicMonthsCount As Integer = MonthsDifference(publisherRecord.BeganPublishing, Now)
			If historicMonthsCount < 13 Then
				historicMonthsCount = 13
			End If

			Dim testMonth As DateTime

			For x = 0 To historicMonthsCount
				Dim linqX = x
				'we are counting backwards
				testMonth = Now.AddMonths(-linqX).FirstOfTheMonth
				If myPublisherRecords.Where(Function(y) y.ReportMonth.FirstOfTheMonth = testMonth).Count = 0 Then
					'we have to add a mock default record for the missing month
					myPublisherRecords.Add(New VM_PublisherCardRecord(_PublisherID, testMonth))
				End If
			Next

			'add in future months that already have data
			'this will allow adding in auxiliary pioneers for months to come
			Dim futureMonthCount As Integer
			Do While myPublisherRecords.Where(Function(y) y.ReportMonth.FirstOfTheMonth = Now.AddMonths(futureMonthCount).FirstOfTheMonth).Count > 0
				futureMonthCount += 1
			Loop
			'the current month (x=0) has already been added above
			'For x = 1 To futureMonthCount
			myPublisherRecords.Add(New VM_PublisherCardRecord(_PublisherID, Now.AddMonths(futureMonthCount).FirstOfTheMonth))
			'Next x
		End If

		For Each myRecord In myPublisherRecords.OrderByDescending(Function(x) x.ReportMonth)
			_AllPublisherRecords.Add(myRecord)
		Next
		'End Using
	End Sub

#Region "IDisposable Support"
	Private disposedValue As Boolean ' To detect redundant calls

	' IDisposable
	Protected Overridable Sub Dispose(disposing As Boolean)
		If Not Me.disposedValue Then
			If disposing Then
				' TODO: dispose managed state (managed objects).
				db.Dispose()
			End If

			' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
			' TODO: set large fields to null.
		End If
		Me.disposedValue = True
	End Sub

	' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
	'Protected Overrides Sub Finalize()
	'    ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
	'    Dispose(False)
	'    MyBase.Finalize()
	'End Sub

	' This code added by Visual Basic to correctly implement the disposable pattern.
	Public Sub Dispose() Implements IDisposable.Dispose
		' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
		Dispose(True)
		GC.SuppressFinalize(Me)
	End Sub
#End Region

End Class
